package top.conangao.uaa.authentication;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.lang.Nullable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import top.conangao.common.constant.CommonConstants;
import top.conangao.uaa.constant.SecurityConstants;

import java.util.HashMap;
import java.util.Map;

import static top.conangao.uaa.util.SecurityUtils.getParameters;

/**
 * @author ConanGao
 * @description
 * @since 2023/11/20 11:58
 **/
public class PasswordGrantAuthenticationConverter implements AuthenticationConverter {
    @Nullable
    @Override
    public Authentication convert(HttpServletRequest request) {
        // 判断认证方式是否是密码登录授权
        String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
        if (!SecurityConstants.GRANT_TYPE_PASSWORD_CODE.equals(grantType)) {
            return null;
        }
        // 获取上下文中的客户端信息
        Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
        //获取请求参数
        MultiValueMap<String, String> parameters = getParameters(request);
        // 判断是否有username参数
        String username = parameters.getFirst(OAuth2ParameterNames.USERNAME);
        if (!StringUtils.hasText(username) || parameters.get(OAuth2ParameterNames.USERNAME).size() != 1) {
            throw new OAuth2AuthenticationException("用户名不能为空");
        }
        // 判断是否有password参数
        String password = parameters.getFirst(OAuth2ParameterNames.PASSWORD);
        if (!StringUtils.hasText(password) || parameters.get(OAuth2ParameterNames.PASSWORD).size() != 1) {
            throw new OAuth2AuthenticationException("密码不能为空");
        }
        // 判断是否有tenant_id参数
        String tenantId = parameters.getFirst(CommonConstants.TENANTCOLUMN);
        if (!StringUtils.hasText(tenantId) || parameters.get(CommonConstants.TENANTCOLUMN).size() != 1) {
            throw new OAuth2AuthenticationException("所属租户不能为空");
        }
        // 提取额外参数
        Map<String, Object> additionalParameters = new HashMap<>();
        parameters.forEach((key, value) -> {
            if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) && !key.equals(OAuth2ParameterNames.CLIENT_ID)) {
                additionalParameters.put(key, value.get(0));
            }
        });

        return new PasswordGrantAuthenticationToken(
                new AuthorizationGrantType(SecurityConstants.GRANT_TYPE_PASSWORD_CODE), 
                clientPrincipal, additionalParameters);
    }
}
